// 泛型就是泛指的类型，在定义函数、类和接口的时候，先不指定类型，等到运行时再指定某一类型
// 使用泛型有一个好处，就是可以减少使用any这种不确定的类型
// 定义泛型的时候我们常用T表示某种未知的类型，使用T只是一个约定，事实上可以使用你想用的字符
function createArray(length, value) {
    var res = [];
    for (var i = 0; i < length; i++) {
        res.push(value);
    }
    return res;
}
// 然后在调用时才指定T的具体类型
console.log(createArray(5, 1)); // [1,1,1,1,1]
console.log(createArray(5, '1')); // ['1','1','1','1','1']
// 也可以不指定类型，ts会根据类型推论得到类型
console.log(createArray(5, '1')); // ['1','1','1','1','1']
// 多个泛型参数
// 如果一个函数有多个泛型参数，那就定义多个泛型类型
// 例如我们要实现一个交换两个变量的函数
function swap(t) {
    return [t[1], t[0]];
}
console.log(swap([1, '2'])); // ['2', 1]
function getLength(value) {
    return value.length; // T上面可能不存在length，因此需要泛型约束
}
// 泛型参数彼此之间也是可以相互约束的
function copyFields(target, source) {
    for (var id in source) {
        target[id] = source[id];
    }
    return target;
}
var x = { a: 1, b: 2, c: 3, d: 4 };
copyFields(x, { b: 10, d: 20 });
// 注意在使用泛型接口时，需要指定泛型接口的类型。一般为any
var createArray2 = function (length, value) {
    var res = [];
    for (var i = 0; i < length; i++) {
        res.push(value);
    }
    return res;
};
console.log(createArray2(4, 'a')); // ['a', 'a', 'a', 'a']
// 泛型类
// 与泛型接口类似，泛型也可以用于定义类
var AddNumber = /** @class */ (function () {
    function AddNumber() {
    }
    return AddNumber;
}());
var addNumber = new AddNumber();
addNumber.value = 0;
addNumber.add = function (x, y) {
    return x + y;
};
console.log(addNumber.add(1, 2));
// 泛型参数的默认类型
// 同函数的默认参数类似，泛型也可以设置默认类型，当泛型在使用时没有传入参数类型，并且无法通过类型推论得到类型的话，就会使用默认类型
function createArray3(length, value) {
    var res = [];
    for (var i = 0; i < length; i++) {
        res.push(value);
    }
    return res;
}
